#include "../myTime.hpp"
#include <iostream>
#include <map>
#include <random>
#include <string>
#include <unordered_map>
#include <vector>
using namespace std;

struct IntRandom {
  std::random_device rd;
  std::mt19937 gen;
  std::uniform_int_distribution<> dist;
  std::default_random_engine dgen;

  /**
   * @brief 左闭右闭
   *
   * @param begin
   * @param end
   */
  IntRandom(int begin, int end) : rd{}, gen(rd()), dist(begin, end), dgen{} {}

  int operator()() { return dist(gen); }
  /**
   * @brief 每次程序运行产生的数据相同
   *
   * @param a 可以是任意整数
   * @return int
   */
  int operator()(int a) { return dist(dgen); }
};

/**
 * @brief 输入文本，统计其单词出现数目
 *
 * @return int
 */
int main() {

  const int num = 500000;

  unordered_map<int, int> ump(num);
  map<int, int> mp;
  vector<int> vec(num);
  for (int i = 0; i < num; ++i) {
    ump[i] = i;
    mp[i] = i;
    vec[i] = i;
  }

  IntRandom rd(0, num - 1);

  const int test_num = 10000000;
  int count{0};

  MyTimer(0, "unordered_map");
  for (int i = 0; i < test_num; ++i) {
    ump[test_num % num] = count++;
  }
  MyTimer(1);

  MyTimer(0, "map");
  for (int i = 0; i < test_num; ++i) {
    mp[test_num % num] = count++;
  }
  MyTimer(1);

  MyTimer(0, "vector");
  for (int i = 0; i < test_num; ++i) {
    vec[test_num % num] = count++;
  }
  MyTimer(1);

  unordered_map<int, int> unmp(test_num);
  map<int, int> mmp;
  std::vector<int> ivec(test_num);
  // 下面两个操作最费时  其中map很费时
  MyTimer(0, "unordered_map");
  for (int i = 0; i < test_num; ++i) {
    unmp[i] = i;
  }
  cout << sizeof(unmp) << endl;
  MyTimer(1);

  MyTimer(0, "map");
  for (int i = 0; i < test_num; ++i) {
    mmp[i] = i;
  }
  cout << sizeof(mmp) << endl;
  MyTimer(1);

  MyTimer(0, "vector");
  for (int i = 0; i < test_num; ++i) {
    ivec[i] = i;
  }
  cout << sizeof(ivec) << endl;
  MyTimer(1);

  MyTimer(0, "unordered_map");
  for (auto iter = unmp.begin(); iter != unmp.end(); ++iter) {
    iter->second *= 2;
  }
  MyTimer(1);

  MyTimer(0, "map");
  for (auto iter = mmp.begin(); iter != mmp.end(); ++iter) {
    iter->second *= 2;
  }
  MyTimer(1);

  return 0;
}